package com.jingge.autojob.skeleton.model.handler;

import com.jingge.autojob.skeleton.annotation.RemoteJob;
import com.jingge.autojob.skeleton.enumerate.RemoteProtocolType;
import com.jingge.autojob.skeleton.enumerate.SchedulingStrategy;
import com.jingge.autojob.skeleton.framework.config.AutoJobRetryConfig;
import com.jingge.autojob.skeleton.framework.config.AutoJobShardingConfig;
import com.jingge.autojob.skeleton.framework.task.AutoJobTask;
import com.jingge.autojob.skeleton.framework.task.AutoJobWrapper;
import com.jingge.autojob.skeleton.model.builder.AutoJobRemoteTaskBuilder;
import com.jingge.autojob.skeleton.model.builder.RemoteJobConfig;
import com.jingge.autojob.util.bean.ObjectUtil;
import com.jingge.autojob.util.http.HttpUtil;
import com.jingge.autojob.util.id.IdGenerator;
import com.jingge.autojob.util.message.MessageManager;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author JingGe(* ^ ▽ ^ *)
 * @date 2023-09-13 10:04
 * @email 1158055613@qq.com
 */
@Slf4j
public class RemoteAutoJobWrapper implements AutoJobWrapper {
    @Override
    public AutoJobTask wrapper(Method method, Class<?> clazz) {
        if (method == null || clazz == null) {
            return null;
        }
        RemoteJob remoteJob = method.getAnnotation(RemoteJob.class);
        if (remoteJob == null) {
            return null;
        }
        if (!RemoteJobConfig.class.isAssignableFrom(method.getReturnType())) {
            log.warn("方法：{}#{}的返回类型不符合注解@RemoteJob的要求", clazz.getName(), method.getName());
            return null;
        }
        try {
            RemoteJobConfig config = (RemoteJobConfig) method.invoke(ObjectUtil
                    .getClassInstance(remoteJob.methodObjectFactory())
                    .createMethodObject(null, clazz));
            if (config == null) {
                return null;
            }
            long taskID = IdGenerator.getNextIdAsLong();
            AutoJobShardingConfig shardingConfig = new AutoJobShardingConfig(taskID, remoteJob
                    .shardingConfig()
                    .enable(), remoteJob
                    .shardingConfig()
                    .total()).setEnableShardingRetry(remoteJob
                    .shardingConfig()
                    .enableShardingRetry());
            AutoJobRetryConfig retryConfig = remoteJob
                    .retryConfig()
                    .useDefault() ? new AutoJobRetryConfig().setTaskId(taskID) : new AutoJobRetryConfig(remoteJob
                    .retryConfig()
                    .enable(), remoteJob
                    .retryConfig()
                    .retryStrategy(), remoteJob
                    .retryConfig()
                    .retryTimes(), remoteJob
                    .retryConfig()
                    .interval(), taskID);
            List<Long> childTaskList = SchedulingStrategy.splitChildTaskId(remoteJob.childTasksId());
            if (remoteJob.protocolType() == RemoteProtocolType.HTTP || remoteJob.protocolType() == RemoteProtocolType.HTTPS) {
                String url = HttpUtil
                        .urlBuilder(HttpUtil.getQueryParams(config.getQueryParams()))
                        .host(config.getHost())
                        .port(config.getPort())
                        .scheme(remoteJob
                                .protocolType()
                                .getType())
                        .addPathSegments(config.getUri())
                        .build()
                        .toString();
                Map<String, Object> queryParams = HttpUtil.getQueryParams(config.getQueryParams());
                return new AutoJobRemoteTaskBuilder(taskID)
                        .setShardingConfig(shardingConfig)
                        .setRetryConfig(retryConfig)
                        .setTaskAlias("Empty".equals(remoteJob.alias()) ? MessageManager.formatMsgLikeSlf4j("{}:{}-{}", config.getHost(), config.getPort(), remoteJob
                                .protocolType()
                                .getType()) : remoteJob.alias())
                        .setTaskId(taskID)
                        .setVersionID(remoteJob.versionID() == -1 ? null : remoteJob.versionID())
                        .setTaskType(remoteJob.taskType())
                        .setLoadBalancingStrategy(remoteJob.loadBalancingStrategy())
                        .setSaveStrategy(remoteJob.saveStrategy())
                        .setTrigger(config
                                .getTrigger()
                                .setChildTask(childTaskList))
                        .setConnectTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS)
                        .setReadTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS)
                        .setWriteTimeout(config.getWriteTimeout(), TimeUnit.MILLISECONDS)
                        .createAsHttpTask(url, remoteJob.reqType(), config.getHeader() == null ? HttpUtil.defaultHeader() : HttpUtil.getHeaders(config.getHeader()), queryParams, config.getBody())
                        .setInterceptor(ObjectUtil.getClassInstance(remoteJob.interceptor()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
